﻿using System.Linq;
namespace _1_Where
{
    internal class Program
    {
        static void Main(string[] args)
        {
            int[] nums = new int[] { 1, 33, 44, 32, 9, 8, 383, 187, 3, 23 };
            //var result = nums.Where(i => i > 10);
            //var result = nums.MyWhere1(i => i > 10);
            var result = MyWhere2(nums, i => i > 10);
            foreach (var item in result)
            {
                Console.WriteLine(item);
            }

            Console.WriteLine($"总个数：{nums.Count()}"); //元素总个数
            Console.WriteLine($"其中大于100的有{nums.Count(i => i > 100)}个"); //符合条件的元素个数

            Console.WriteLine(nums.Any());//是否有元素
            Console.WriteLine(nums.Any(i => i < 10)); //是否有符合条件的元素

            //Console.WriteLine(nums.Single());   //只有一个元素时使用(有且只有一个元素)，否则报错。所以这里会报错
            Console.WriteLine(nums.Single(i => i == 33));
            //Console.WriteLine(nums.SingleOrDefault());  //最多只有一条元素时使用（没有元素则返回默认值），否则报错。所以这里会报错
            Console.WriteLine(nums.SingleOrDefault(i => i < 2));    //最多只有一条符合条件的元素时使用（没有符合条件的元素则返回默认值），否则报错。

            //Console.WriteLine(nums.First());  //获取第一个元素，如果没有元素则报错
            //Console.WriteLine(nums.First(i => i > 1000)); //获取第一个符合条件的元素，如果没有符合条件的元素则报错
            //Console.WriteLine(nums.FirstOrDefault()); //获取第一个元素，如果没有元素则返回默认值
            //Console.WriteLine(nums.FirstOrDefault(i => i > 1000)); //获取第一个符合条件的元素，如果没有符合条件的元素则返回默认值

            //随机排序一：
            var result2 = nums.OrderBy(i=>Guid.NewGuid()); //随机排序
            Console.WriteLine("随机排序结果1：");
            foreach (var item in result2)
            {
                Console.WriteLine(item);
            }

            //随机排序二：
            Random random = new Random();
            var result3 = nums.OrderBy(i => random.Next()); //随机排序
            Console.WriteLine("随机排序结果2：");
            foreach (var item in result3)
            {
                Console.WriteLine(item);
            }

            //多条件排序：orderby/orderbydescending + thenby/thenbydescending
            List<Student> students = new List<Student>()
            {
                new Student(){ Id=1, Name="张三", Age=18},
                new Student(){ Id=2, Name="李四", Age=20},
                new Student(){ Id=3, Name="王五", Age=17},
                new Student(){ Id=4, Name="赵六", Age=19},
                new Student(){ Id=4, Name="前七", Age=20},
            };

            //不要写成了 OrderBy().OrderBy()，那样会覆盖前面的排序条件，以最后一个为准
            var sortedStudents = students.OrderByDescending(s => s.Age).ThenBy(s => s.Name);
            Console.WriteLine("多条件排序结果：");
            foreach (var student in sortedStudents)
            {
                Console.WriteLine($"Id:{student.Id}, Name:{student.Name}, Age:{student.Age}");
            }

            //获取数据：take(n),如果数据量不足n，则获取全部数据
            Console.WriteLine("\n\n获取前2个学生信息：");
            foreach (var item in students.Take(2))
            {
                Console.WriteLine(item);
            }

            //跳过数据：skip(n)，如果数据量不足n，则不获取任何数据
            Console.WriteLine("\n\n跳过前10个学生信息：");
            foreach (var item in students.Skip(10))
            {
                Console.WriteLine(item);
            }

        }

        public static IEnumerable<T> MyWhere2<T>(IEnumerable<T> source, Func<T, bool> predicate)
        {
            List<T> list = new List<T>();
            foreach (var item in source)
            {
                if (predicate(item))
                {
                    list.Add(item);
                }
            }
            return list;
        }
    }

    public static class MyLinqExtensions
    {
        public static IEnumerable<T> MyWhere1<T>(this IEnumerable<T> source, Func<T, bool> predicate)
        {
            foreach (var item in source)
            {
                if (predicate(item))
                {
                    yield return item;
                }
            }
        }
    }

    class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }

        override public string ToString()
        {
            return $"Id:{Id}, Name:{Name}, Age:{Age}";
        }
    }
}
